// SPDX-FileCopyrightText: Adam Evyčędo
//
// SPDX-License-Identifier: AGPL-3.0-or-later

package traffic

import (
	"bufio"
	"encoding/csv"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"golang.org/x/text/transform"
)

type LondonDft struct {
	client http.Client
}

func (LondonDft) getTimezone() *time.Location {
	l, _ := time.LoadLocation("Europe/London")
	return l
}

func (g LondonDft) ConvertVehicles() ([]Vehicle, error) {
	return []Vehicle{}, nil
}

func (z LondonDft) GetVersions(_ time.Time, timezone *time.Location) ([]Version, error) {
	version, err := MakeVersionTimezone("00010101_99991231", timezone)
	version.Link = "https://data.bus-data.dft.gov.uk/timetable/download/gtfs-file/london/"
	return []Version{version}, err
}

func (LondonDft) String() string {
	return "london_dft"
}

func (LondonDft) RealtimeFeeds() map[RealtimeFeedType]string {
	return map[RealtimeFeedType]string{
		VEHICLE_POSITIONS: "https://data.bus-data.dft.gov.uk/avl/download/gtfsrt | zip gtfsrt.bin",
	}
}

func (LondonDft) Transformer() transform.Transformer {
	return transform.Nop
}

func (LondonDft) Name() string {
	return "London DfT"
}

func (LondonDft) Flags() FeedFlags {
	return FeedFlags{
		Headsign:     HeadsignTripHeadsing,
		StopIdFormat: "{{stop_id}}",
		StopName:     "{{stop_name}}",
		LineName:     "{{route_short_name}}",
	}
}

func (LondonDft) FeedPrepareZip(path string) error {
	// NOTE fix routes
	routesFile, err := os.Open(filepath.Join(path, "routes.txt"))
	if err != nil {
		return fmt.Errorf("while opening routes file: %w", err)
	}
	defer routesFile.Close()
	routes2File, err := os.OpenFile(filepath.Join(path, "routes2.txt"), os.O_RDWR|os.O_CREATE, 0644)
	if err != nil {
		return fmt.Errorf("while opening routes2 file: %w", err)
	}
	defer routes2File.Close()
	r := csv.NewReader(bufio.NewReader(routesFile))
	w := csv.NewWriter(routes2File)
	header, err := r.Read()
	if err != nil {
		return fmt.Errorf("while reading routes header: %w", err)
	}
	fields := map[string]int{}
	for i, headerField := range header {
		fields[headerField] = i
	}
	if _, ok := fields["route_color"]; !ok {
		header = append(header, "route_color")
	}
	err = w.Write(header)
	if err != nil {
		return fmt.Errorf("while writing routes header: %w", err)
	}

	for {
		record, err := r.Read()
		if err == io.EOF {
			break
		}
		if err != nil {
			return fmt.Errorf("while reading a route record: %w", err)
		}
		// NOTE fix route types
		if record[fields["route_short_name"]] == "London Cable Car" {
			record[fields["route_type"]] = "6"
		}
		if record[fields["route_type"]] == "200" {
			record[fields["route_type"]] = "3"
		}

		// NOTE fix route colours
		colour := "ffffff"
		if record[fields["route_short_name"]] == "Bakerloo" {
			colour = "A45A2A"
		}
		if record[fields["route_short_name"]] == "Central" {
			colour = "DA291C"
		}
		if record[fields["route_short_name"]] == "Circle" {
			colour = "FFCD00"
		}
		if record[fields["route_short_name"]] == "District" {
			colour = "007A33"
		}
		if record[fields["route_short_name"]] == "Hammersmith & City" {
			colour = "E89CAE"
		}
		if record[fields["route_short_name"]] == "Jubilee" {
			colour = "7C878E"
		}
		if record[fields["route_short_name"]] == "Metropolitan" {
			colour = "840B55"
		}
		if record[fields["route_short_name"]] == "Northern" {
			colour = "000000"
		}
		if record[fields["route_short_name"]] == "Piccadilly" {
			colour = "10069F"
		}
		if record[fields["route_short_name"]] == "Victoria" {
			colour = "00A3E0"
		}
		if record[fields["route_short_name"]] == "Waterloo & City" {
			colour = "6ECEB2"
		}
		ix, ok := fields["route_color"]
		if !ok {
			record = append(record, colour)
		} else {
			record[ix] = colour
		}

		// NOTE fix underscore
		record[fields["route_short_name"]] = strings.ReplaceAll(record[fields["route_short_name"]], "_", " ")

		err = w.Write(record)
		if err != nil {
			return fmt.Errorf("while writing a route record: %w", err)
		}
	}
	w.Flush()
	err = os.Remove(filepath.Join(path, "routes.txt"))
	if err != nil {
		return fmt.Errorf("while removing routes: %w", err)
	}
	err = os.Rename(filepath.Join(path, "routes2.txt"), filepath.Join(path, "routes.txt"))
	if err != nil {
		return fmt.Errorf("while renaming routes: %w", err)
	}
	return nil
}

func (LondonDft) QRInfo() (string, QRLocation, string) {
	return "", QRLocationNone, ""
}
